{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "I1JiGtmRbLVp"
      },
      "source": [
        "##### Copyright 2021 The TF-Agents Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "nQnmcm0oI1Q-"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xCnjvyteX4in"
      },
      "source": [
        "# Introduction to Multi-Armed Bandits\n",
        "\n",
        "\u003ctable class=\"tfo-notebook-buttons\" align=\"left\"\u003e\n",
        "  \u003ctd\u003e\n",
        "    \u003ca target=\"_blank\" href=\"https://www.tensorflow.org/agents/tutorials/intro_bandit\"\u003e\n",
        "    \u003cimg src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" /\u003e\n",
        "    View on TensorFlow.org\u003c/a\u003e\n",
        "  \u003c/td\u003e\n",
        "  \u003ctd\u003e\n",
        "    \u003ca target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/agents/blob/master/docs/tutorials/intro_bandit.ipynb\"\u003e\n",
        "    \u003cimg src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" /\u003e\n",
        "    Run in Google Colab\u003c/a\u003e\n",
        "  \u003c/td\u003e\n",
        "  \u003ctd\u003e\n",
        "    \u003ca target=\"_blank\" href=\"https://github.com/tensorflow/agents/blob/master/docs/tutorials/intro_bandit.ipynb\"\u003e\n",
        "    \u003cimg src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" /\u003e\n",
        "    View source on GitHub\u003c/a\u003e\n",
        "  \u003c/td\u003e\n",
        "  \u003ctd\u003e\n",
        "    \u003ca href=\"https://storage.googleapis.com/tensorflow_docs/agents/docs/tutorials/intro_bandit.ipynb\"\u003e\u003cimg src=\"https://www.tensorflow.org/images/download_logo_32px.png\" /\u003eDownload notebook\u003c/a\u003e\n",
        "  \u003c/td\u003e\n",
        "\u003c/table\u003e"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b5tItHFpLyXG"
      },
      "source": [
        "## Introduction\n",
        "\n",
        "Multi-Armed Bandit (MAB) is a Machine Learning framework in which an agent has to select actions (arms) in order to maximize its cumulative reward in the long term. In each round, the agent receives some information about the current state (context), then it chooses an action based on this information and the experience gathered in previous rounds. At the end of each round, the agent receives the reward assiociated with the chosen action.\n",
        "\n",
        "Perhaps the purest example is the problem that lent its name to MAB: imagine that we are faced with `k` slot machines (one-armed bandits), and we need to figure out which one has the best payout, while not losing too much money. \n",
        "\n",
        "![Multi-Armed Bandits](https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Las_Vegas_slot_machines.jpg/320px-Las_Vegas_slot_machines.jpg)\n",
        "\n",
        "Trying each machine once and then choosing the one that paid the most would not be a good strategy: The agent could fall into choosing a machine that had a lucky outcome in the beginning but is suboptimal in general. Instead, the agent should repeatedly come back to choosing machines that do not look so good, in order to collect more information about them. This is the main challenge in Multi-Armed Bandits: the agent has to find the right mixture between exploiting prior knowledge and exploring so as to avoid overlooking the optimal actions.\n",
        "\n",
        "More practical instances of MAB involve a piece of side information every time the learner makes a decision. We call this side information \"context\" or \"observation\". \n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Y2gzFh2YwJAj"
      },
      "source": [
        "## Multi-Armed Bandits and Reinforcement Learning\n",
        "\n",
        "Why is there a MAB Suite in the TF-Agents library? What is the connection between RL and MAB? Multi-Armed Bandits can be thought of as a special case of Reinforcement Learning. To quote [Intro to RL](https://www.tensorflow.org/agents/tutorials/0_intro_rl):\n",
        "\n",
        "*At each time step, the agent takes an action on the environment based on its policy $\\pi(a_t|s_t)$, where $s_t$ is the current observation from the environment, and receives a reward $r_{t+1}$ and the next observation $s_{t+1}$ from the environment. The goal is to improve the policy so as to maximize the sum of rewards (return).*\n",
        "\n",
        "In the general RL case, the next observation $s_{t+1}$ depends on the previous state $s_t$ and the action $a_t$ taken by the policy. This last part is what separates MAB from RL: in MAB, the next state, which is the observation, does not depend on the action chosen by the agent.\n",
        "\n",
        "This similarity allows us to reuse all the concepts that exist in TF-Agents.\n",
        "\n",
        "\n",
        "*   An **environment** outputs observations, and responds to actions with rewards.\n",
        "*   A **policy** outputs an action based on an observation, and\n",
        "*   An **agent** repeatedly updates the policy based on previous observation-action-reward tuples.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "KA1ELdJrfJaV"
      },
      "source": [
        "## The Mushroom Environment\n",
        "\n",
        "For illustrative purposes, we use a toy example called the \"Mushroom Environment\". The mushroom dataset ([Schlimmer, 1981](https://archive.ics.uci.edu/ml/datasets/Mushroom)) consists of labeled examples of edible and poisonous mushrooms. Features include shapes, colors, sizes of different parts of the mushroom, as well as odor and many more.\n",
        "\n",
        "![mushroom](https://archive.ics.uci.edu/ml/assets/MLimages/Large73.jpg)\n",
        "\n",
        "The mushroom dataset, just like all supervised learning datasets, can be turned into a contextual MAB problem. We use the method also used by [Riquelme et al. (2018)](https://arxiv.org/pdf/1802.09127.pdf). In this conversion, the agent receives the features of a mushroom, decides to eat it or not. Eating an edible mushroom results in a reward of +5, while eating a poisonous mushroom will give either +5 or -35 with equal probability. Not eating the mushroom results in 0 reward, independently of the type of the mushroom. The following table summarizes the reward assignments:\n",
        "\n",
        "\u003e```\n",
        "           | edible | poisonous\n",
        "-----------|--------|----------\n",
        "eating it  |     +5 | -35 / +5\n",
        "leaving it |      0 |        0\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VXdlbTmc8yMt"
      },
      "source": [
        "##  The LinUCB Agent\n",
        "Performing well in a contextual bandit environment requires a good estimate on the reward function of each action, given the observation. One possibility is to estimate the reward function with linear functions. That is, for every action $i$, we are trying to find the parameter $\\theta_i\\in\\mathbb R^d$ for which the estimates\n",
        "\n",
        "$r_{t, i} \\sim \\langle v_t, \\theta_i\\rangle$\n",
        "\n",
        "are as close to the reality as possible. Here $v_t\\in\\mathbb R^d$ is the context received at time step $t$. Then, if the agent is very confident in its estimates, it can choose $\\arg\\max_{1, ..., K}\\langle v_t, \\theta_k\\rangle$ to get the highest expected reward.\n",
        "\n",
        "As explained above, simply choosing the arm with the best estimated reward does not lead to a good strategy. There are many different ways to mix exploitation and exploration in linear estimator agents, and one of the most famous is the Linear Upper Confidence Bound (LinUCB) algorithm (see e.g. [Li et al. 2010](https://arxiv.org/abs/1003.0146)). LinUCB has two main building blocks (with some details omitted):\n",
        "\n",
        "1.   It maintains estimates for the parameters of every arm with Linear Least Squares: $\\hat\\theta_i\\sim X^+_i r_i$, where $X_i$ and $r_i$ are the stacked contexts and rewards of rounds where arm $i$ was chosen, and $()^+$ is the pseudo inverse.\n",
        "2.   It maintains *confidence ellipsoids* defined by the inverse covariance $X_i^\\top X_i$ for the above estimates.\n",
        "\n",
        "\n",
        "\n",
        "\n",
        "The main idea of LinUCB is that of \"Optimisim in the Face of Uncertainty\". The agent incorporates exploration via boosting the estimates by an amount that corresponds to the variance of those estimates. That is where the confidence ellipsoids come into the picture: for every arm, the optimistic estimate is $\\hat r_i = \\max_{\\theta\\in E_i}\\langle v_t, \\theta\\rangle$, where $E_i$ is the ellipsoid around $\\hat\\theta_i$. The agent chooses best looking arm $\\arg\\max_i\\hat r_i$.\n",
        "\n",
        "Of course the above description is just an intuitive but superficial summary of what LinUCB does. An implementation can be found in our codebase [here](https://github.com/tensorflow/agents/blob/master/tf_agents/bandits/agents/lin_ucb_agent.py)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "r-Fc1dYdD1YM"
      },
      "source": [
        "## What's Next?\n",
        "If you want to have a more detailed tutorial on our Bandits library take a look at our [tutorial for Bandits](https://colab.research.google.com/github/tensorflow/agents/blob/master/docs/tutorials/bandits_tutorial.ipynb). If, instead, you would like to start exploring our library right away, you can find it [here](https://github.com/tensorflow/agents/tree/master/tf_agents/bandits). If you are even more eager to start training, look at some of our end-to-end examples [here](https://github.com/tensorflow/agents/tree/master/tf_agents/bandits/agents/examples/v2), including the above described mushroom environment with LinUCB [here](https://github.com/tensorflow/agents/tree/master/tf_agents/bandits/agents/examples/v2/train_eval_mushroom.py). "
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [
        "I1JiGtmRbLVp"
      ],
      "name": "intro_bandit.ipynb",
      "provenance": [],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
